package com.uzai.console.service.wxpub.impl;

import com.alibaba.fastjson.JSONObject;
import com.uzai.common.enums.RedisCacheKeyEnum;
import com.uzai.common.exception.BusinessException;
import com.uzai.common.result.ResponseCode;
import com.uzai.console.config.UzaiConsoleSysConfig;
import com.uzai.console.dto.wxpub.ActionInfo;
import com.uzai.console.dto.wxpub.Scene;
import com.uzai.console.dto.wxpub.WxpubAccredit;
import com.uzai.console.service.wxpub.WxpubService;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: jianghan
 * @Date: 2019/12/23 10:01
 * @Description:
 */
@Service
public class WxpubServiceImpl implements WxpubService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UzaiConsoleSysConfig uzaiConsoleSysConfig;

    private static Logger logger = LoggerFactory.getLogger(WxpubServiceImpl.class);

    @Override
    public Object accredit(WxpubAccredit wxpubAccredit) {
        logger.info("accredit info is:{}",wxpubAccredit.toString());
        return Long.parseLong(wxpubAccredit.getEchostr());
    }

    @Override
    //处理消息
    public Object msg(Map<String,String> params) {
        try {
            // 事件消息
            if (params!=null && "subscribe".equals(params.get("Event"))){// 关注事件
                // 获取openid
                String openid = params.get("FromUserName");
                // 获取运营商id_随机参数key
                String eventKey = params.get("EventKey");
                if (StringUtils.isNotBlank(eventKey)){
                    String[] eventKeyArr = eventKey.split("_");
                    if(eventKeyArr != null & eventKeyArr.length == 3){
                        String paraKey = eventKeyArr[1] + "_" + eventKeyArr[2];
                        //将openid存放到缓存当中
                        redisTemplate.opsForValue().set(String.format(RedisCacheKeyEnum.WXPUB_OPENID.getKey(), paraKey), openid, 2, TimeUnit.MINUTES);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("err:{}",e);
        }
        return null;
    }

    @Override
    public String getAccessToken(String appid, String secret) {
        String accessToken = (String) redisTemplate.opsForValue().get(String.format(RedisCacheKeyEnum.WXPUB_TOKEN.getKey(), appid));
        if (StringUtils.isNotBlank(accessToken)){
            return accessToken;
        }
        String access_token = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String token_url = uzaiConsoleSysConfig.getWxpubAccessToken();
        token_url = token_url+"&appid="+appid+"&secret="+ secret;
        HttpGet httpget = new HttpGet(token_url);
        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpget);
            HttpEntity entity = response.getEntity();
            String content = EntityUtils.toString(entity);
            logger.info("pull access_token info:{} ",content);
            Map<String,String> map = JSONObject.parseObject(content,Map.class);
            access_token = map.get("access_token");
            if (StringUtils.isBlank(access_token)){
                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "获取token失败");
            }
            redisTemplate.opsForValue().set(String.format(RedisCacheKeyEnum.WXPUB_TOKEN.getKey(), appid), access_token, 100, TimeUnit.MINUTES);
        } catch (Exception e) {
            logger.error("pull access_token error:{}",e);
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION,"获取token失败");
        } finally {
            try {
                response.close();
                httpclient.close();
            } catch (IOException e) {
                response = null;
                httpclient = null;
            }
        }
        return access_token;
    }

    @Override
    public String getNewAccessToken(String appid, String secret) {
        redisTemplate.delete(String.format(RedisCacheKeyEnum.WXPUB_TOKEN.getKey(), appid));
        return getAccessToken(appid,secret);
    }

    /**
     * 获取带参数的公众号二维码
     * @param paraKey 自定义参数
     * @return
     */
    @Override
    public String getWxpubQrCode(String paraKey) {
        String wxpub_appid = uzaiConsoleSysConfig.getWxpubAppid();
        String wxpub_secret = uzaiConsoleSysConfig.getWxpubAppsecret();

        String token = getAccessToken(wxpub_appid, wxpub_secret);
        String url = uzaiConsoleSysConfig.getWxpubQrcodeCreate()+"?access_token="+token;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpclient = null;
        String ticket = "";
        try {
            Map<String,Object> param = new HashMap<>();
            param.put("expire_seconds","2592000");
            param.put("action_name","QR_STR_SCENE");

            ActionInfo actionInfo = new ActionInfo();
            Scene scene = new Scene();
            scene.setScene_str(paraKey);
            actionInfo.setScene(scene);
            param.put("action_info",actionInfo);

            String json = JSONObject.toJSONString(param);
            logger.info("qrcode create info:{}",json);

            httpclient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
            StringEntity se = new StringEntity(json,"UTF-8");
            se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
            httpPost.setEntity(se);

            response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, "UTF-8");
            logger.info("qrcode create result info:{}",result);

            if (result.contains("access_token is invalid")){
                token = getNewAccessToken(wxpub_appid,wxpub_secret);
                url = uzaiConsoleSysConfig.getWxpubQrcodeCreate()+"?access_token="+token;
                httpPost = new HttpPost(url);
                httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
                se = new StringEntity(json,"UTF-8");
                se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
                httpPost.setEntity(se);

                response = httpclient.execute(httpPost);
                entity = response.getEntity();
                result = EntityUtils.toString(entity, "UTF-8");
                logger.info("qrcode create result info:{}",result);
            }

            Map<String,String> resultMap = JSONObject.parseObject(result,Map.class);
            StringBuilder stringBuilder = new StringBuilder(uzaiConsoleSysConfig.getWxpubQrcodeUrl());
            stringBuilder.append(resultMap.get("ticket"));
            ticket = stringBuilder.toString();
        } catch (IOException e) {
            logger.error("qrcode create err:",e);
        }finally {
            try {
                response.close();
                httpclient.close();
            } catch (IOException e) {
                response = null;
                httpclient = null;
            }
        }
        return ticket;
    }

}
